package main

import "fmt"

// 对每个状态所不同的行为进行描述
type State interface {
	OpenDoor(c *Context)
	CloseDoor(c *Context)
	Run(c *Context, targetFloor int)
	Stop(c *Context)
}

// 故障状态
type IdleState struct {
}

func (s *IdleState) OpenDoor(c *Context) {
	fmt.Println("门已打开")
}
func (s *IdleState) CloseDoor(c *Context) {
	fmt.Println("门已关闭")
}
func (s *IdleState) Run(c *Context, targetFloor int) {
	fmt.Println("电梯故障中。。。")
}
func (s *IdleState) Stop(c *Context) {
	c.SetState(&StopState{})
	fmt.Println("电梯已恢复")
}

// 运行状态
type RunState struct {
}

func (s *RunState) OpenDoor(c *Context) {
	fmt.Println("电梯正在运行中")
}

func (s *RunState) CloseDoor(c *Context) {
	fmt.Println("门已关闭")
}

func (s *RunState) Run(c *Context, targetFloor int) {
	fmt.Println("电梯正在运行中")
}

func (s *RunState) Stop(c *Context) {
	c.SetState(&IdleState{})
	fmt.Println("电梯已停止")
}

// 驻留状态
type StopState struct {
}

func (s *StopState) OpenDoor(c *Context) {
	fmt.Println("门已打开")
}

func (s *StopState) CloseDoor(c *Context) {
	fmt.Println("正在关门")
}

func (s *StopState) Run(c *Context, targetFloor int) {
	if targetFloor != c.CurrentFloor {
		c.SetState(&RunState{})
		c.CurrentFloor = targetFloor
		fmt.Println("电梯正在前往")
	} else {
		fmt.Println("正处于该层")
	}
}

func (s *StopState) Stop(c *Context) {
	c.SetState(&IdleState{})
	fmt.Println("电梯已停止")
}

// 实体上下文，实体的行为由当前的状态决定
type Context struct {
	CurrentFloor int
	state        State
}

func (c *Context) SetState(state State) {
	c.state = state
}

func (c *Context) OpenDoor() {
	c.state.OpenDoor(c)
}

func (c *Context) CloseDoor() {
	c.state.CloseDoor(c)
}

func (c *Context) Run(targetFloor int) {
	c.state.Run(c, targetFloor)
}

func (c *Context) Stop() {
	c.state.Stop(c)
}

func main() {
	c := &Context{
		CurrentFloor: 1,
		state:        &IdleState{},
	}

	c.OpenDoor()
	c.CloseDoor()
	c.Run(5)
	c.Stop()

	c.OpenDoor()
	c.CloseDoor()
	c.Run(3)
	c.Stop()

}
